#include "uart.h"
#include "bsp/cpu_driver.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
#include "utils/circle_buffer.h"

static hw_call_back rx_cb_;
static void* ctx_;
static c_buffer_t *tx_queue_;
static c_buffer_t _rx_queue_;
static c_buffer_t *rx_queue_ = &_rx_queue_;
static u8 rx_cache[CONFIG_UART_RX_BUFFER_SIZE];

void uart_init(unsigned char hw_id, unsigned int rate, hw_call_back cb, void *ctx) {
	rx_cb_ = cb;
	ctx_ = ctx;
	circle_buffer_init(rx_queue_, rx_cache, sizeof(rx_cache));
	MX_USB_DEVICE_Init();
}

void uart_tx_poll(unsigned char hw_id) {
	u8 buffer[32];
	while(true) {
		if (CDC_Transmit_isBusy() == USBD_BUSY || !CDC_Is_Connected()) {
			break;
		}
		u16 len = circle_get_bytes(tx_queue_, buffer, sizeof(buffer));
		if (len <= 0) {
			break;
		}
		CDC_Transmit_FS(buffer, len);
	}
}

void uart_rx_poll(unsigned char hw_id) {
	u8 buffer[32];
	while(true) {
		u16 len = circle_get_bytes(rx_queue_, buffer, sizeof(buffer));
		if (len <= 0) {
			break;
		}
		if (rx_cb_) {
			rx_cb_(ctx_, buffer, len);
		}
	}
}

void uart_set_dma_queue(unsigned char hw_id, void *queue) {
	tx_queue_ = (c_buffer_t *)queue;
}


void usb_uart_rx_handler(u8 *data, u32 len) {
	circle_put_bytes(rx_queue_, data, len);
}
